import {iMicroTokenInfo} from "@peryl/micro-web";
import {http} from "../modules/plain-design/http";
import {createCache} from "@peryl/react-compose";
import {env} from "../env";
import {createEnum} from "@peryl/utils/createEnum";

export const LoginService = (() => {

  const eLoginStatus = createEnum([
    /*登录已经过期*/
    'EXPIRE',
    /*登录已经失效*/
    'INVALID'
  ] as const);

  /*缓存登录信息*/
  const loginCache = createCache<iMicroTokenInfo>(() => ({
    envName: env.envName,
    cacheName: '@@LOGIN'
  }));

  /*账号密码登录*/
  const loginPassword = async (username: string, password: string): Promise<iMicroTokenInfo> => {
    const data = await http.post<{ result: iMicroTokenInfo }>('/login', { username, password }, { noToken: true });
    /*登录成功，本地缓存*/
    loginCache.save(data.result);
    return data.result;
  };

  /*获取token*/
  const getToken = (() => {

    let _tokenInfo: iMicroTokenInfo | undefined = undefined;

    return async (): Promise<iMicroTokenInfo> => {

      if (!_tokenInfo) {
        _tokenInfo = await (async () => {
          const cacheData = loginCache.get();
          if (!cacheData) {
            // 登录时间过期
            throw new Error(eLoginStatus.EXPIRE);
          }
          if (cacheData.expire <= Date.now()) {
            throw new Error(eLoginStatus.EXPIRE);
          }
          try {
            /*主动请求后端检查登录是否有效*/
            console.log('-->> check loginExpire');
            const resp = await http.post('/loginExpire', {}, { noToken: true });
            if (resp.fail) {
              /*登录已经失效，需要重新登录*/
              throw new Error(eLoginStatus.INVALID);
            } else {
              /*有效，返回登录信息*/
              return cacheData;
            }
          } catch (e) {
            /*登录已经失效，需要重新登录*/
            console.error(e);
            throw new Error(eLoginStatus.INVALID);
          }
        })();
      }

      return _tokenInfo;
    };
  })();

  /*清空tokenInfo*/
  const clear = () => {
    loginCache.save(null);
  };

  /*根据token请求tokenInfo信息*/
  const getTokenInfo = async (token: string, autoCache = true): Promise<iMicroTokenInfo> => {
    const data = await http.post<{ result: iMicroTokenInfo }>('/getTokenInfo', { token }, { noToken: true });
    if (autoCache) {
      loginCache.save(data.result);
    }
    return data.result;
  };

  return {
    loginPassword,
    getToken,
    clear,
    getTokenInfo,
  };
})();
